package com.keepsport.keepsportapi.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.keepsport.keepsportapi.config.RedisKeyConfig;
import com.keepsport.keepsportapi.dao.UserDao;
import com.keepsport.keepsportapi.dao.UserDetailDao;
import com.keepsport.keepsportapi.dao.UserLogDao;
import com.keepsport.keepsportapi.dto.UserAddDto;
import com.keepsport.keepsportapi.dto.UserFindDto;
import com.keepsport.keepsportapi.dto.UserLoginDto;
import com.keepsport.keepsportapi.entity.User;
import com.keepsport.keepsportapi.entity.UserDetail;
import com.keepsport.keepsportapi.entity.UserLog;
import com.keepsport.keepsportapi.service.intf.UserService;
import com.keepsport.keepsportapi.type.UserLogType;
import com.keepsport.keepsportapi.utils.JedisUtil;
import com.keepsport.keepsportapi.utils.PassUtils;
import com.keepsport.keepsportapi.utils.StringUtil;
import com.keepsport.keepsportapi.vo.R;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;

/**
 * 　　　　　   　▍ ★∴
 * 　　　．．．．▍▍．..．█▍ ☆ ★∵ ..../
 * 　　 　◥█▅▅██▅▅██▅▅▅▅▅▅▅▅▅███◤
 * 　　 　．◥███████████████◤
 * 　 ～～～～◥█████████████◤～～～～
 *
 * @author dyb
 * @create 2022-06-29 17:13
 */
@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserDao dao;
    @Resource
    private UserLogDao logDao;
    @Resource
    private UserDetailDao detailDao;

    @Override
    public R checkPhone(String phone) {
        //1.验证
        if(StringUtil.isPhone(phone)){
            //2.查询数据库
            User user=dao.selectOne(new QueryWrapper<User>().eq("phone",phone));
            //3.验证是否存在
            if(user!=null){
                //手机号存在
                return R.ok();
            }
        }
        return R.fail();
    }
    //账号登录 唯一 一个账号 在线1个
    @Override
    public R loginByName(UserLoginDto dto) {
        //1.入参校验
        if(dto!=null){
            if(StringUtil.isNotEmpty(dto.getName(),dto.getPassword())){

                //2.查询数据库 支持手机号或用户名 登录
                QueryWrapper<User> queryWrapper=new QueryWrapper<>();
                queryWrapper.eq("name",dto.getName());
                queryWrapper.or().eq("phone",dto.getName());
                User user=dao.selectOne(queryWrapper);

                //3.验证是否存在用户
                if(user!=null){

                    //4.验证密码
                    if(PassUtils.md5(dto.getPassword()).equals(user.getPassword())){

                        //5.校验 当前账号是否在线  唯一登录
                        if(JedisUtil.checkKey(RedisKeyConfig.LOGIN_UID+user.getId())){
                            return R.fail("亲,账号已在线，请勿重复登录！");
                        }else {
                            //本次 可以登录

                            //登录成功 令牌：成功标记 Token 可以很简单也可以很复杂
                            //前后端分离开发中，登录成功标记采用令牌的形式，令牌:Token 登录成功的标记，一般是用户信息
                            //登录分为2种：1.无状态登录(服务端不记录登录信息) 2.有状态登录(服务端记录登录信息)

                            //6.令牌 存储在Redis 有效期 1.用什么数据类型 2.存储什么数据 3.有没有有效期
                            //记录 令牌和对应的用户信息
                            JedisUtil.addString(RedisKeyConfig.LOGIN_UID + user.getId(), JSON.toJSONString(user), RedisKeyConfig.LOGIN_UID_TIME);

                            //记录日志
                            logDao.insert(new UserLog(user.getId(), UserLogType.登录.getValue(),"完成了账号密码登录",dto.getCity(),dto.getMobie()));
                            //7.返回信息和令牌
                            return R.ok(user.getId());
                        }
                    }
                }
            }
        }
        return R.fail("亲，账号或密码错误！");
    }
    //手机验证码登录
    @Override
    public R loginByPhone(UserLoginDto dto) {
        //1.入参校验
        if(dto!=null){
            if(StringUtil.isNotEmpty(dto.getName(),dto.getPassword())){

                //2.查询数据库 支持手机号或用户名 登录
                QueryWrapper<User> queryWrapper=new QueryWrapper<>();
                queryWrapper.eq("name",dto.getName());
                queryWrapper.or().eq("phone",dto.getName());
                User user=dao.selectOne(queryWrapper);

                //3.验证是否存在用户
                if(user!=null){

                    //4.验证 验证码
                   if(dto.getPassword().equals(JedisUtil.getString(RedisKeyConfig.SMS_CODE_LOGIN+dto.getName()))){

                        //5.校验 当前账号是否在线  唯一登录
                        if(JedisUtil.checkKey(RedisKeyConfig.LOGIN_UID+user.getId())){
                            return R.fail("亲,账号已在线，请勿重复登录！");
                        }else {
                            //6.令牌 存储在Redis 有效期 1.用什么数据类型 2.存储什么数据 3.有没有有效期
                            //记录 令牌和对应的用户信息
                            JedisUtil.addString(RedisKeyConfig.LOGIN_UID + user.getId(), JSON.toJSONString(user), RedisKeyConfig.LOGIN_UID_TIME);

                            //记录日志
                            logDao.insert(new UserLog(user.getId(), UserLogType.登录.getValue(),"完成了手机号验证码登录",dto.getCity(),dto.getMobie()));

                            //7.返回信息和令牌
                            return R.ok(user.getId());
                        }
                    }
                }
            }
        }
        return R.fail("亲，账号或密码错误！");
    }
    @Transactional //开启事务
    @Override
    public R findPass(UserFindDto dto) {
        //1.入参校验
        if(dto!=null){
            if(StringUtil.isNotEmpty(dto.getPhone(),dto.getCode(),dto.getPassword())){

                //2查询数据库 获取当前用户
                QueryWrapper<User> queryWrapper=new QueryWrapper<>();
                queryWrapper.eq("phone",dto.getPhone());
                User user=dao.selectOne(queryWrapper);

                //3校验用户是否存在
                if(user!=null) {
                    //4.校验验证码
                    if (dto.getCode().equals(JedisUtil.getString(RedisKeyConfig.SMS_CODE_FIND + dto.getPhone()))) {

                        //5.修改密码
                        if (dao.updatePass(dto.getPhone(), dto.getPassword()) > 0) {

                            //6.修改成功 记录日志
                            logDao.insert(new UserLog(user.getId(), UserLogType.密码找回.getValue(), "进行了密码找回，重置成功！", dto.getCity(), dto.getMobie()));

                            //7.如果当前账号有在线，需要下线
                            if(JedisUtil.checkKey(RedisKeyConfig.LOGIN_UID+user.getId())){
                                JedisUtil.delKeys(RedisKeyConfig.LOGIN_UID+user.getId());
                            }
                            return R.ok();
                        }
                    }
                }
            }
        }
        return R.fail();
    }

    @Override
    public R loginOut(int token) {
        //1.验证
        if(token>0){
            //2.校验 令牌是否存在
            if(JedisUtil.checkKey(RedisKeyConfig.LOGIN_UID+token)){
                //3.注销 删除
                JedisUtil.delKeys(RedisKeyConfig.LOGIN_UID+token);
                return R.ok();
            }
        }
        return R.fail();
    }
    @Override
    public R outByname(String name) {
        //1.验证
        if(dao.selectOne((new QueryWrapper<User>()).eq("name",name))!=null){
            //2.校验 令牌是否存在
            if(JedisUtil.checkKey(RedisKeyConfig.LOGIN_UID+dao.selectId(name))){
                //3.注销 删除
                JedisUtil.delKeys(RedisKeyConfig.LOGIN_UID+dao.selectId(name));
                return R.ok();
            }
        }
        return R.fail();
    }

    @Override
    public R checkName(String name) {
        //1.参数校验
        if(StringUtils.hasLength(name)){
            //2.查询
            QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
            queryWrapper.eq("name",name);
            User user=dao.selectOne(queryWrapper);
            //3.验证
            if(user==null){
                return R.ok();
            }else {
                return R.fail("账号已存在！");
            }
        }
        return R.fail("非法参数！");
    }

    @Override
    public R save(UserAddDto dto){
            String url="https://tupian.qqw21.com/article/UploadPic/2020-4/202042720591047805.jpg";
            User user = new User(dto.getName(),dto.getPhone(),PassUtils.md5(dto.getPassword()),url);

        if (dao.insert(user)==1){
            int uid = dao.selectId(dto.getName());
            UserDetail userDetail = new UserDetail(uid);
            if (detailDao.insert(userDetail)==1){
                return R.ok();
            }

            }

        return R.fail();
    }
}

